#include "W5500.h"
#include "spi.h"

unsigned char mac[6]= {0x00,0x98,0xdc,0x42,0x61,0x11};/*local mac*/
unsigned char ip[4]= {192,168,0,10};  /* local ip*/
unsigned char sub[4]= {255,255,255,0};  /*subnet mask*/
unsigned char gw[4]= {192,168,0,1}; /*gateway ip*/



unsigned char txsize[MAX_SOCK_NUM] = {8,2,1,1,1,1,1,1};				 
unsigned char rxsize[MAX_SOCK_NUM] = {8,2,1,1,1,1,1,1};        
static unsigned char I_STATUS[MAX_SOCK_NUM];                   
static unsigned short int SSIZE[MAX_SOCK_NUM];                 
static unsigned short int RSIZE[MAX_SOCK_NUM];                 
																															 
static void delay(int ms);

unsigned char Info[4]= {0,0,0,0};


void W5500_Init(void)
{
	GPIO_InitTypeDef GPIO_Initure;	
	__HAL_RCC_GPIOI_CLK_ENABLE();
	__HAL_RCC_GPIOE_CLK_ENABLE();
	
    GPIO_Initure.Pin=W5500_RST_PIN; 
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  
    GPIO_Initure.Pull=GPIO_PULLUP;          
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     
    HAL_GPIO_Init(W5500_RST_PORT,&GPIO_Initure);	    
																					  
	/*PE6  W5500_CS*/	                        
//		GPIO_Initure.Pin=GPIO_PIN_6;          
//    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP 
//    GPIO_Initure.Pull=GPIO_PULLUP;        
//    GPIO_Initure.Speed=GPIO_SPEED_HIGH;   
//    HAL_GPIO_Init(GPIOE,&GPIO_Initure);   
																					  
//	/*PG9  W5500_CS*/	                        
//		GPIO_Initure.Pin=GPIO_PIN_9;            
//    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  
//    GPIO_Initure.Pull=GPIO_PULLUP;          
//    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     
//    HAL_GPIO_Init(GPIOG,&GPIO_Initure);     
																					  
	/*PC1 W5500_CS*/                          
		GPIO_Initure.Pin=W5500_CS_PIN;            
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  
    GPIO_Initure.Pull=GPIO_PULLUP;          
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     
    HAL_GPIO_Init(W5500_CS_PORT,&GPIO_Initure);     
																					  
	W5500_RST=1;
	W5500_CS=1;
	
 
	
	delay(2000);
	//while((IINCHIP_READ(PHYCFGR)& LINK)==0);     			 
	setMR( MR_RST );							 
	delay(100);	
	
	W5500_RST=0;
	delay(100);
	W5500_RST=1;
	delay(100);
	
	setSHAR(mac);							 
	setSUBR(sub);							 
	setGAR(gw);								 
	setSIPR(ip);							 
	sysinit(txsize,rxsize);		 
	setRTR(2000);              
	setRCR(8);                 
	IINCHIP_WRITE( IMR,IM_IR7 | IM_IR6);  
	IINCHIP_WRITE( SIMR, S0_IMR); 				 
	IINCHIP_WRITE( Sn_IMR(0), IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);
}
 void   Plat_Net_Init(void)
 {
		W5500_Init();
	 	//GetW5500SetInfo();
 }

void GetW5500SetInfo(void)
{
	getSIPR(Info);
	printf("IP: %d. %d. %d. %d\r\n",Info[0],Info[1],Info[2],Info[3]);
	getSUBR(Info);
	printf("SN: %d. %d. %d. %d\r\n",Info[0],Info[1],Info[2],Info[3]);
	getGAR(Info);
	printf("GW: %d. %d. %d. %d\r\n",Info[0],Info[1],Info[2],Info[3]);
	getRTR(Info);
	printf("PTR: %d \r\n",Info[0]*256+Info[1] );	
	getRTR(Info);
	printf("RCR: %d \r\n",Info[0]  );	
	getMR(Info);
	printf("MR: %d \r\n",Info[0]  );	
	getINTLEVEL(Info );
	printf("INTLEVEL: %d \r\n",Info[0]*256+Info[1]  ); 
	printf("IR: %X \r\n",getIR( )  );	
	printf("IMR: %X \r\n",getIMR( )  );	
	printf("SIMR: %X \r\n",getSIMR( )  );		
	printf("Sn_IMR(0): %X \r\n",getSn_IMR(0 )  );		
	
	
	getUIPR(Info);
	printf("UIPR: %d. %d. %d. %d\r\n",Info[0],Info[1],Info[2],Info[3]);
	getUPORT(Info);
	printf("UPORT: %d \r\n",Info[0]*256+Info[1] );
 
}

 

unsigned char getISR(unsigned char s)
{
  return I_STATUS[s];
}

void putISR(unsigned char s, unsigned char val)
{
   I_STATUS[s] = val;
}

unsigned short int getIINCHIP_RxMAX(unsigned char s)
{
   return RSIZE[s];
}

unsigned short int getIINCHIP_TxMAX(unsigned char s)
{
   return SSIZE[s];
}

void IINCHIP_CSoff(void)
{
	//SPI1_CS_OFF;
	W5500_CS=0;
}

void IINCHIP_CSon(void)
{
	//SPI1_CS_ON;
	W5500_CS=1;
}

unsigned char  IINCHIP_SpiSendData(unsigned char dat)
{
   //return(spi1.send_data(dat));
	return(SPI5_ReadWriteByte(dat));
}

void IINCHIP_WRITE( u32 addrbsb,  u8 data)
{
   //SPI1_CS_OFF;
   W5500_CS=0;
   SPI5_ReadWriteByte( (addrbsb & 0x00FF0000)>>16);                                // Address byte 1
   SPI5_ReadWriteByte( (addrbsb & 0x0000FF00)>> 8);                                // Address byte 2
   SPI5_ReadWriteByte( (addrbsb & 0x000000F8) + 4);                                // Data write command and Write data length 1
		SPI5_ReadWriteByte(data);                                                       // Data write (write 1byte data)
   //SPI1_CS_ON;
   W5500_CS=1;
}

unsigned char IINCHIP_READ(u32 addrbsb)
{
   unsigned char data = 0;
	
   W5500_CS=0;	
   SPI5_ReadWriteByte( (addrbsb & 0x00FF0000)>>16);                                // Address byte 1
   SPI5_ReadWriteByte( (addrbsb & 0x0000FF00)>> 8);                                // Address byte 2
   SPI5_ReadWriteByte( (addrbsb & 0x000000F8))    ;                                // Data read command and Read data length 1
   data = SPI5_ReadWriteByte(0x00); 
   W5500_CS=1;
	
   return data;  
}

unsigned short int wiz_write_buf(u32 addrbsb,u8* buf,u16 len)
{
	 unsigned short int idx = 0;	 
   //SPI1_CS_OFF;
	W5500_CS=0;
   SPI5_ReadWriteByte( (addrbsb & 0x00FF0000)>>16);                                // Address byte 1
   SPI5_ReadWriteByte( (addrbsb & 0x0000FF00)>> 8);                                // Address byte 2
   SPI5_ReadWriteByte( (addrbsb & 0x000000F8) + 4);                                // Data write command and Write data length 1
   for(idx = 0; idx < len; idx++)                                              // Write data in loop
   {
     SPI5_ReadWriteByte(buf[idx]);
   }
   //SPI1_CS_ON;
   W5500_CS=1;
   return len; 
}

unsigned short int wiz_read_buf(u32 addrbsb, u8* buf,u16 len)
{
	unsigned short int idx = 0;
	//SPI1_CS_OFF;
	W5500_CS=0;
	SPI5_ReadWriteByte( (addrbsb & 0x00FF0000)>>16);                                 // Address byte 1
	SPI5_ReadWriteByte( (addrbsb & 0x0000FF00)>> 8);                                 // Address byte 2
	SPI5_ReadWriteByte( (addrbsb & 0x000000F8));                                     // Data write command and Write data length 1
	for(idx = 0; idx < len; idx++)                                               // Write data in loop
	{
		buf[idx] = SPI5_ReadWriteByte(0x00);
	}
	//SPI1_CS_ON;
	W5500_CS=1;	
	return len;
}


void iinchip_init(void)
{
  setMR( MR_RST );
}

void sysinit( unsigned char * tx_size, unsigned char * rx_size  )
{
  short int i;
  short int ssum,rsum;
  ssum = 0;
  rsum = 0;

  for (i = 0 ; i < MAX_SOCK_NUM; i++)                      // Set the size, masking and base address of Tx & Rx memory by each channel
  {
		IINCHIP_WRITE( (Sn_TXMEM_SIZE(i)), tx_size[i]);
		IINCHIP_WRITE( (Sn_RXMEM_SIZE(i)), rx_size[i]);
          
    SSIZE[i] = (s16)(0);
    RSIZE[i] = (s16)(0);


    if (ssum <= 16384)
    {
         switch( tx_size[i] )
      {
      case 1:
        SSIZE[i] = (s16)(1024);
        break;
      case 2:
        SSIZE[i] = (s16)(2048);
        break;
      case 4:
        SSIZE[i] = (s16)(4096);
        break;
      case 8:
        SSIZE[i] = (s16)(8192);
        break;
      case 16:
        SSIZE[i] = (s16)(16384);
      break;
      default :
        RSIZE[i] = (s16)(2048);
        break;
      }
    }

   if (rsum <= 16384)
    {
         switch( rx_size[i] )
      {
      case 1:
        RSIZE[i] = (s16)(1024);
        break;
      case 2:
        RSIZE[i] = (s16)(2048);
        break;
      case 4:
        RSIZE[i] = (s16)(4096);
        break;
      case 8:
        RSIZE[i] = (s16)(8192);
        break;
      case 16:
        RSIZE[i] = (s16)(16384);
        break;
      default :
        RSIZE[i] = (s16)(2048);
        break;
      }
    }
    ssum += SSIZE[i];
    rsum += RSIZE[i];

  }
}


void setGAR(unsigned char * addr)
{
    wiz_write_buf(GAR0, addr, 4);
}


void getGWIP(unsigned char * addr)
{
    wiz_read_buf(GAR0, addr, 4);
}


void setSUBR(unsigned char * addr)
{   
    wiz_write_buf(SUBR0, addr, 4);
}

void setSHAR(unsigned char * addr)
{
  wiz_write_buf(SHAR0, addr, 6);  
}


void setSIPR(unsigned char * addr)
{
    wiz_write_buf(SIPR0, addr, 4);  
}

void getGAR(unsigned char * addr)
{
    wiz_read_buf(GAR0, addr, 4);
}

void getSUBR(unsigned char * addr)
{
    wiz_read_buf(SUBR0, addr, 4);
}

void getSHAR(unsigned char * addr)
{
    wiz_read_buf(SHAR0, addr, 6);
}

void getSIPR(unsigned char * addr)
{
    wiz_read_buf(SIPR0, addr, 4);
}
void getUIPR(unsigned char * addr)
{
    wiz_read_buf(UIPR0, addr, 4);
}

void getUPORT(unsigned char * addr)
{
    wiz_read_buf(UPORT0, addr, 2);
}
void setMR(unsigned char val)
{
	IINCHIP_WRITE(MR,val);
}
void getMR(unsigned char * addr)
{
    wiz_read_buf(MR, addr, 1);
}
void getINTLEVEL(unsigned char * addr)
{
    wiz_read_buf(INTLEVEL0, addr, 2);
}
unsigned char getIR( void )
{
	return IINCHIP_READ(IMR);
}
unsigned char getSIMR( void )
{
	return IINCHIP_READ(SIMR);
}
unsigned char getIMR( void )
{
	return IINCHIP_READ(IR);
}
void setRTR(unsigned short int timeout)
{
  IINCHIP_WRITE(RTR0,(unsigned char)((timeout & 0xff00) >> 8));
  IINCHIP_WRITE(RTR1,(unsigned char)(timeout & 0x00ff));
}
void getRTR(unsigned char * addr)
{
    wiz_read_buf(RTR0, addr, 2);
}
void setRCR(unsigned char retry)
{
  IINCHIP_WRITE(WIZ_RCR,retry);
}
void getRCR(unsigned char * addr)
{
    wiz_read_buf(WIZ_RCR, addr, 1);
}
void clearIR(unsigned char mask)
{
  IINCHIP_WRITE(IR, ~mask | getIR() ); // must be setted 0x10.
}

void setSn_MSS(SOCKET s, unsigned short int Sn_MSSR)
{
  IINCHIP_WRITE( Sn_MSSR0(s), (unsigned char)((Sn_MSSR & 0xff00) >> 8));
  IINCHIP_WRITE( Sn_MSSR1(s), (unsigned char)(Sn_MSSR & 0x00ff));
}

void setSn_TTL(SOCKET s, unsigned char ttl)
{    
   IINCHIP_WRITE( Sn_TTL(s) , ttl);
}

unsigned char getSn_IR(SOCKET s)
{
   return IINCHIP_READ(Sn_IR(s));
}
unsigned char getSn_IMR(SOCKET s)
{
   return IINCHIP_READ(Sn_IMR(s));
}
unsigned char getSn_SR(SOCKET s)
{
   return IINCHIP_READ(Sn_SR(s));
}

unsigned short int getSn_TX_FSR(SOCKET s)
{
  unsigned short int val=0,val1=0;
  do
  {
    val1 = IINCHIP_READ(Sn_TX_FSR0(s));
    val1 = (val1 << 8) + IINCHIP_READ(Sn_TX_FSR1(s));
      if (val1 != 0)
    {
        val = IINCHIP_READ(Sn_TX_FSR0(s));
        val = (val << 8) + IINCHIP_READ(Sn_TX_FSR1(s));
    }
  } while (val != val1);
   return val;
}

unsigned short int getSn_RX_RSR(SOCKET s)
{
  unsigned short int val=0,val1=0;
  do
  {
    val1 = IINCHIP_READ(Sn_RX_RSR0(s));
    val1 = (val1 << 8) + IINCHIP_READ(Sn_RX_RSR1(s));
    if(val1 != 0)
    {
        val = IINCHIP_READ(Sn_RX_RSR0(s));
        val = (val << 8) + IINCHIP_READ(Sn_RX_RSR1(s));
    }
  } while (val != val1);
   return val;
}

void send_data_processing(SOCKET s, unsigned char *data, unsigned short int len)
{
  unsigned short int ptr = 0;
  unsigned long int addrbsb = 0;
  ptr = IINCHIP_READ( Sn_TX_WR0(s) );
  ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR1(s));

  addrbsb = ((u32)ptr<<8) + (s<<5) + 0x10;
  wiz_write_buf(addrbsb, data, len);

  ptr += len;
  IINCHIP_WRITE( Sn_TX_WR0(s) ,(u8)((ptr & 0xff00) >> 8));
  IINCHIP_WRITE( Sn_TX_WR1(s),(u8)(ptr & 0x00ff));
}

void recv_data_processing(SOCKET s, unsigned char *data, unsigned short int len)
{
  unsigned short int ptr = 0;
  unsigned long int addrbsb = 0;
  
  ptr = IINCHIP_READ( Sn_RX_RD0(s) );
  ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ( Sn_RX_RD1(s) );

  addrbsb = ((u32)ptr<<8) + (s<<5) + 0x18;
  wiz_read_buf(addrbsb, data, len);
  ptr += len;

  IINCHIP_WRITE( Sn_RX_RD0(s), (u8)((ptr & 0xff00) >> 8));
  IINCHIP_WRITE( Sn_RX_RD1(s), (u8)(ptr & 0x00ff));
}

void setSn_IR(unsigned char s, unsigned char val)
{
    IINCHIP_WRITE(Sn_IR(s), val);
}

 

static void delay(int ct) //ms
{
	int i, j;
	for (i = 0; i < ct; i++) 
	{
		for (j = 0; j < 10000; j++) ;
	}
}


